package org.redmagic.agent;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;

import org.redmagic.PlaceholderReplacer;
import org.redmagic.agent.utils.LocalHostProperties;
import org.redmagic.exception.RedMagicException;
import org.redmagic.utils.Conditions;
import org.redmagic.utils.Documents;
import org.redmagic.utils.Files;
import org.redmagic.utils.Properties2;
import org.w3c.dom.Document;

/**
 * Resolves configurable properties within a files contents, using (optional)
 * setup files to pull properties from.
 */
@ParametersAreNonnullByDefault
public class MagicFileConfigurer {

    private final PlaceholderReplacer replacer;
    private final String targetFileName;
    private final List<String> setupFileNames;
    private final Object lock;

    private Document targetFileContents;

    public MagicFileConfigurer(String targetFileName, PlaceholderReplacer replacer) {
        this(targetFileName, new ArrayList<String>(), replacer);
    }

    public MagicFileConfigurer(String targetFileName, List<String> setupFileNames, PlaceholderReplacer replacer) {
        this.targetFileName = Conditions.notNull(targetFileName, "targetFileName");
        this.setupFileNames = Conditions.notNull(setupFileNames, "setupFileNames");
        this.replacer = Conditions.notNull(replacer, "replacer");
        this.lock = new Object();
    }

    @Nonnull
    public Document getResolvedContents() {
        synchronized(lock) {
        	if (targetFileContents == null) {
        		String fileContents = getContents();
        		targetFileContents = Documents.parseContents(fileContents, true);
        	}
        	return targetFileContents;        	
        }
    }

    private String getContents() {
        Properties resolvedProperties = LocalHostProperties.retrieve();
        return resolveProperties(resolvedProperties);
    }

    private String resolveProperties(Properties resolvedProperties) {
        loadSetupProperties(resolvedProperties);
        return resolveMagicProperties(resolvedProperties);
    }

    private void loadSetupProperties(Properties resolvedProperties) {
        for (String setupFileName : setupFileNames) {
            setupFileName = replacer.replacePlaceholders(setupFileName, resolvedProperties);
            Properties2.loadProperties(setupFileName, resolvedProperties);
        }
    }

    private String resolveMagicProperties(Properties resolvedProperties) {
        try {
            String fileName = replacer.replacePlaceholders(targetFileName, resolvedProperties);
            String contents = Files.toString(fileName);
            return replacer.replacePlaceholders(contents, resolvedProperties);
        } catch (IOException ioe) {
            throw new RedMagicException(ioe.getMessage(), ioe);
        }
    }
}